'''
Created on 2011-3-1

@author: jeffrey
'''

from functools import wraps
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, Http404, HttpResponse
from weibopy import OAuthHandler, API
from google.appengine.api import users 
#douban api
from douban.service import DoubanService
import datetime
import json


from models import *
from forms import *
import service

sns_oauth_params={'sina':{'name':'sina',
                          'consumer_key':'2431073663', 
                          'consumer_secret':'d9848a58a1cb745b3ffce8efcad4eaa5',
                          'OAUTH_HOST':'api.t.sina.com.cn',
                          'OAUTH_ROOT':'/oauth/'},
                'douban':{'name':'douban',
                          'consumer_key':'04291c346216d8dc0c7b549d26448a94', 
                          'consumer_secret':'be0b62bd1945dcb9',
                          'OAUTH_HOST':'www.douban.com/service',
                          'OAUTH_ROOT':'/auth/'}
                }


def requires_login(method):
    @wraps(method)
    def wrapper(request, *args, **kwargs):
        if not request.session.get('user', None):
            return HttpResponseRedirect('/login')
        
        return method(request, *args, **kwargs)
    return wrapper

@requires_login
def index(request):
    user = request.session['user']
    user_statistic = service.getUserStatisticList({'user': user}).get()
    grade = service.getUserGrade(user)
    tag_list = service.getTagList(filters={'user': user}, orderby='-createtime', pagesize=5)    
    return render_to_response('index.html', 
                              {'user': user,
                               'user_statistic': user_statistic,
                               'grade': grade,
                               'tag_list': tag_list,
                               })

'''
The gettodaymessages method return JSON.
The method call by ajax in index.html
'''
@requires_login
def gettodaymessages(request):
    user = request.session['user']
    pagenum = request.GET.get('pagenum', 1)
    today = datetime.date.today()
    #message_list = service.getMessageList({'receiveuser': user, 'receivetime >=': today}, '-receivetime', 10, int(pagenum))
    message_list = service.getMessageList(pagesize=10, pagenum=1)    
    data = json.encode(message_list)
    return HttpResponse(data)

'''
The getoldmessages method return JSON.
The method call by ajax in index.html
'''
@requires_login
def getoldmessages(request):
    user = request.session['user']
    pagenum = request.GET.get('pagenum', 1)
    today = datetime.date.today()
    #message_list = service.getMessageList({'receiveuser': user, 'receivetime <': today}, '-receivetime', 10, int(pagenum))
    message_list = service.getMessageList(pagesize=10, pagenum=1)
    data = json.encode(message_list)
    return HttpResponse(data)

def login(request):
    initData()
    sns_list = service.getSNSList(orderby='-createtime')        
    return render_to_response('login.html', 
                              {'sns_list': sns_list})

def logout(request):
    request.session.clear()
    return HttpResponseRedirect('/')

@requires_login
def setting(request):
    user = request.session['user']
    form = UserForm(data=request.POST or None, instance=user)
    
    if not request.POST:
        return render_to_response('common_add_edit.html', 
                                  {'action': '/setting/', 
                                   'user': user,
                                   'form': form})
    
    errors = form.errors
    if not errors:
        try:
            user = form.save(commit=False)
        except ValueError, err:
            errors['__all__'] = unicode(err)
    
    if errors:
        return render_to_response('common_add_edit.html', 
                                  {'action': '/setting', 
                                   'user': user,
                                   'form': form})
    
    service.saveUser(user)
    request.session['user'] = user

    return HttpResponseRedirect('/')

@requires_login
def message_edit(request, id):
    user = request.session['user']
    message = None
    
    action = '/message/add'
    if id:
        action = '/message/%s' % id
        message = service.getMessage(id)
        if message is None or message.createuser.id <> user.id:
            raise Http404
    
    form = MessageForm(data=request.POST or None, instance=message)
    
    if not request.POST:
        return render_to_response('common_add_edit.html', 
                                  {'action': action, 
                                   'user': user,
                                   'form': form})
    
    errors = form.errors
    if not errors:
        try:
            message = form.save(commit=False)
        except ValueError, err:
            errors['__all__'] = unicode(err)
    
    if errors:
        return render_to_response('common_add_edit.html', 
                                  {'action': action, 
                                   'user': user,
                                   'form': form})
    message.createuser = user
    service.saveMessage(message)

    return HttpResponseRedirect('/outbox')

@requires_login
def message_add(request):
    return message_edit(request, None)

@requires_login
def outbox(request):
    #user = request.session['user']
    #message_list = service.getMessageList({'createuser': user}, '-createtime', 10, 1)
    return render_to_response('outbox.html')

'''
The getoutboxmessages method return JSON.
The method call by ajax in outbox.html
'''
@requires_login
def getoutboxmessages(request):
    user = request.session['user']
    pagenum = request.GET.get('pagenum', 1)    
    message_list = service.getMessageList({'createuser': user}, '-createtime', 10, int(pagenum))    
    data = json.encode(message_list)
    return HttpResponse(data)

'''
The common oauth method, except google.
'''
def oauth(request, id):
    sns = service.getSNS(id)
    if sns:
        return oauth_sns(request, sns.name)
    else:
        raise Http404

'''SNS OAUTH'''
def oauth_sns(request, sns_name):
    ''' Google user login'''
    if sns_name == 'google':
        google_login_url = users.create_login_url(request.build_absolute_uri('/google_callback'))
        return HttpResponseRedirect(google_login_url)
    
    '''From sns_oauth_params dict get the sns oauth parameters'''
    sns_oauth_param = sns_oauth_params.get(str(sns_name))
    if sns_oauth_param == None or len(sns_oauth_param) == 0:
        raise Http404
    
    '''Save the sns oauth parameters into session'''
    request.session['sns_oauth_param'] = sns_oauth_param
    
    '''call oauth to get the request_token and save it into session for later usage'''
    consumer_key = sns_oauth_param.get('consumer_key')
    consumer_secret = sns_oauth_param.get('consumer_secret')
    callback = request.build_absolute_uri('/oauth_callback')
    auth = OAuthHandler(consumer_key=consumer_key, consumer_secret=consumer_secret , callback=callback)
    auth.updateOauthHostRoot(sns_oauth_param.get('OAUTH_HOST'), sns_oauth_param.get('OAUTH_ROOT'))
    authorization_url = auth.get_authorization_url()
    request_token = auth.request_token
    request.session['request_token'] = request_token
    
    '''Direct the sns authorization url to wait user agree'''
    '''if user agree auth, will return to callback page'''
    return HttpResponseRedirect(authorization_url)

'''
SNS Oauth call back method.
'''
def oauth_callback(request):    
    '''get the sns_oauth_param from session'''
    sns_oauth_param=request.session['sns_oauth_param']
    
    '''get the api key and secret'''
    consumer_key = sns_oauth_param.get('consumer_key')
    consumer_secret = sns_oauth_param.get('consumer_secret')
    
    '''get the oauth_verifier from api request'''
    oauth_verifier = request.GET.get('oauth_verifier', None)
    
    '''get the request_token from session'''
    request_token = request.session['request_token']
    
    '''get the access_token by request_token and save it in session for later usage'''
    auth=OAuthHandler(consumer_key, consumer_secret)
    auth.request_token=request_token
    auth.updateOauthHostRoot(sns_oauth_param.get('OAUTH_HOST'), sns_oauth_param.get('OAUTH_ROOT'))
    access_token=auth.get_access_token(oauth_verifier)    
    request.session['oauth_access_token'] = access_token
    
    '''call api to get the snsid'''
    sns_name=sns_oauth_param.get('name')
    sns=service.getSNSList({'name': sns_name}).get()
    snsid = ''
    if sns_name=='sina':
        api = API(auth)
        sina_user = api.me()
        snsid = str(sina_user.id)    
    elif sns_name=='douban':
        douban_service = DoubanService(api_key=consumer_key, secret=consumer_secret)
        douban_service.client.token=auth.access_token
        people = douban_service.GetAuthorizedUID('/people/@me')
        snsid = str(people.uid.text)
    
    '''create a new user or update an exist user'''
    user = addUpdateUser(request, snsid, sns)
    request.session['user'] = user
    return HttpResponseRedirect('/')

'''
Google login call back method
'''
def google_callback(request):
    google_user = users.get_current_user()
    snsid = google_user.user_id()
    sns=service.getSNSList({'name': 'google'}).get()
    user = addUpdateUser(request, snsid, sns)
    request.session['user'] = user
    return HttpResponseRedirect('/')    

'''create a new user or update an exist user'''
def addUpdateUser(request, snsid, sns):
    '''Check if the sns_userid exist in a user'''
    user_sns_list =service.getUserSNSList(filters={'snsid': snsid})
    if not user_sns_list:
        '''Create a new user and no user in session'''
        user = None
        if 'user' in request.session:
            user = request.session['user']
        if user == None:
            user_name='%s_%s' % (sns.name, snsid)
            user=User(name=user_name, credit=1)
            service.saveUser(user)
        '''Create a UserSNS relationship'''
        user_sns = UserSNS(user=user, sns=sns, snsid=snsid)
        service.saveUserSNS(user_sns)
        return user
    else:
        user_sns = user_sns_list[0]
        user = user_sns.user
        today = datetime.date.today()
        lastlogday = user.lastlogtime.date()
        if today > lastlogday:
            add_credit_login = int(service.getParaValue('add_credit_login', '1'))
            user.credit = user.credit + add_credit_login
        
        service.saveUser(user)
        return user

def initData():
    '''Init SNS data'''
    if not service.getSNSList():
        sns = SNS(name='sina', 
                  url='http://t.sina.com.cn', 
                  logo='http://open.sinaimg.cn/wikipic/icon/32x32.png')
        service.saveSNS(sns)
        
        sns = SNS(name='douban',
                  url='http://www.douban.com.cn',
                  logo='http://img3.douban.com/pics/nav/lg_main_a6.png')
        service.saveSNS(sns)
        
        sns = SNS(name='google',
                  url='http://www.google.com',
                  logo='http://www.google.com.hk/images/google_sm.gif')
        service.saveSNS(sns)
    
    if not service.getGradeList():
        grade = Grade(name='1',
                      credit=0,
                      canpost=3,
                      canreceive=3)
        service.saveGrade(grade)
        
        grade = Grade(name='2',
                      credit=10,
                      canpost=4,
                      canreceive=4)
        service.saveGrade(grade)
        
        grade = Grade(name='3',
                      credit=30,
                      canpost=5,
                      canreceive=5)
        service.saveGrade(grade)
        
        grade = Grade(name='4',
                      credit=90,
                      canpost=6,
                      canreceive=6)
        service.saveGrade(grade)
        
        grade = Grade(name='5',
                      credit=300,
                      canpost=7,
                      canreceive=7)
        service.saveGrade(grade)
    
    if not service.getMessageTypeList():
        messageType = MessageType(name='txt', logo='/static/images/txt.jpg')
        service.saveMessageType(messageType)
        
        messageType = MessageType(name='picture', logo='/static/images/picture.jpg')
        service.saveMessageType(messageType)
        
        messageType = MessageType(name='music', logo='/static/images/music.jpg')
        service.saveMessageType(messageType)
        
        messageType = MessageType(name='video', logo='/static/images/video.jpg')
        service.saveMessageType(messageType)
    
    if not service.getSystemParameterList():
        systemParameter = SystemParameter(pkey='add_credit_login', 
                                          pvalue='1', 
                                          description='Add credit for every login everyday')
        service.saveSystemParameter(systemParameter)
        
        systemParameter = SystemParameter(pkey='add_credit_post', 
                                          pvalue='1', 
                                          description='Add credit for every post message')
        service.saveSystemParameter(systemParameter)
        
        systemParameter = SystemParameter(pkey='add_credit_receive', 
                                          pvalue='1', 
                                          description='Add credit for every receive message')
        service.saveSystemParameter(systemParameter)
        
        